# coding:utf-8
from typing import Any

from PyQt6.QtWidgets import QWidget, QFileDialog
from qfluentwidgets import GroupHeaderCardWidget, FluentIcon, PushButton, ComboBox, PrimaryPushButton, SwitchButton, \
    InfoBar
import ffmpeg

from common import cfg, Icon, SingleIcon
from components import BaseScrollArea


def compress_video(
        input_file: str,
        output_file: str,
        scale: str,
        codec: str,
        crf: str,
        preset: str,
        video_bitrate: str,
        acodec: str,
        audio_bitrate: str,
        r: str,
        *,
        overwrite_output: bool = True
):
    """
    使用 ffmpeg-python 压缩视频并调整分辨率
    :param input_file: 输入视频文件路径
    :param output_file: 输出视频文件路径
    :param scale: 压缩后的视频分辨率
    :param codec: 压缩使用的编码器
    :param crf: 压缩质量（28 是推荐值）
    :param preset: 压缩速度选项
    :param video_bitrate: 视频比特率
    :param acodec: 音频编码器
    :param audio_bitrate: 音频比特率
    :param r: 帧率
    """
    scale = scale.split('x')
    scale = f"scale={scale[0]}x{scale[1]}"

    ffmpeg.input(
        input_file
    ).output(
        output_file,  # 输出文件
        vf=scale,  # 设置分辨率
        vcodec=codec,  # 使用 H.264 编码
        crf=crf,  # 压缩质量（28 是推荐值）
        preset=preset,  # 压缩速度选项
        video_bitrate=video_bitrate,  # 视频比特率
        acodec=acodec,  # 音频编码
        audio_bitrate=audio_bitrate,  # 音频比特率
        r=r  # 帧率
    ).run(
        cmd=cfg.ffmpegFolder.value,
        overwrite_output=overwrite_output,
    )


class CompressVideoView(BaseScrollArea):
    VIDEO_SUFFIX = ["WMV", "ASF", "ASX", "RM", "RMVB", "MP4", "3GP", "MOV", "M4V", "AVI", "DAT", "MKV", "FIV", "VOB"]

    icon = SingleIcon.VIDEO_COMPRESSION
    title = '视频压缩'
    description = '使用 FFmpeg 工具压缩视频文件，对视频进行压缩，以节省存储空间或提高播放速度。'
    object_name = 'CompressVideoView'

    def __init__(self, parent: QWidget = None):
        super().__init__(parent)
        self.filename = ''
        self.output_file = ''
        self.headerCard = GroupHeaderCardWidget('使用 ffmpeg 压缩视频（使用前请先安装 ffmpeg）', self)
        self.selectBtn = PushButton(FluentIcon.FOLDER, '选择视频文件', self)
        self.saveBtn = PushButton(FluentIcon.SAVE, '保存视频压缩文件', self)
        self.overwriteOutput = SwitchButton(self)
        self.scaleComboBox = ComboBox(self)
        self.codecComboBox = ComboBox(self)
        self.crfComboBox = ComboBox(self)
        self.presetComboBox = ComboBox(self)
        self.vbComboBox = ComboBox(self)
        self.acodecComboBox = ComboBox(self)
        self.abComboBox = ComboBox(self)
        self.fpsComboBox = ComboBox(self)
        self.startBtn = PrimaryPushButton(FluentIcon.PLAY, '开始压缩', self)

        self.__initWidgets()
        self.__initGroup()
        self.__connectSignals()

    def __initWidgets(self):
        self.setObjectName('CompressVideoView')
        self.setReturnVisible(True)
        self.setToolTipContent('正在压缩视频，请稍候...')

        self.overwriteOutput.setChecked(True)
        self.scaleComboBox.addItems(
            ['160x120', '320x240', '480x360', '640x480', '1280x720', '1280x800', '1280x960', '1920x1080', '1920x1200',
             '2560x1440', '2560x1600', '3840x2160'])
        self.scaleComboBox.setCurrentIndex(6)
        self.codecComboBox.addItems(['libx264', 'libx265', 'libvpx-vp9', 'libaom-av1'])
        self.codecComboBox.setCurrentIndex(0)
        self.crfComboBox.addItems(['18', '23', '28', '32', '41', '50', '58', '64'])
        self.crfComboBox.setCurrentIndex(3)
        self.presetComboBox.addItems(
            ['ultrafast', 'superfast', 'veryfast', 'faster', 'fast', 'medium', 'slow', 'slower', 'veryslow'])
        self.presetComboBox.setCurrentIndex(4)
        self.vbComboBox.addItems(
            ['1000k', '1500k', '2000k', '2500k', '3000k', '3500k', '4000k', '4500k', '5000k', '5500k', '6000k'])
        self.vbComboBox.setCurrentIndex(4)
        self.acodecComboBox.addItems(['aac', 'libfdk_aac', 'libmp3lame', 'libopus', 'libvorbis', 'libwavpack'])
        self.acodecComboBox.setCurrentIndex(0)
        self.abComboBox.addItems(
            ['96k', '128k', '160k', '192k', '224k', '256k', '320k', '384k', '448k', '512k', '576k', '640k'])
        self.abComboBox.setCurrentIndex(4)
        self.fpsComboBox.addItems(['24', '25', '30', '32', '50', '60'])
        self.fpsComboBox.setCurrentIndex(2)

        self.scrollLayout.addWidget(self.headerCard)

    def __initGroup(self):
        self.selectGroup = self.headerCard.addGroup(
            FluentIcon.MOVIE,
            '选择视频文件',
            '请选择要压缩的视频文件',
            self.selectBtn
        )
        self.saveGroup = self.headerCard.addGroup(
            FluentIcon.SAVE_AS,
            '保存压缩文件',
            '请选择压缩后的视频保存路径',
            self.saveBtn
        )
        self.headerCard.addGroup(
            FluentIcon.SAVE_COPY,
            '覆盖输出文件',
            '是否覆盖输出文件',
            self.overwriteOutput
        )
        self.headerCard.addGroup(
            FluentIcon.ZOOM,
            '分辨率',
            '请选择压缩后的视频分辨率',
            self.scaleComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.CODE,
            '编码器',
            '请选择压缩使用的编码器',
            self.codecComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.MARKET,
            '压缩质量',
            '请选择压缩质量（越高压缩率越低）',
            self.crfComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.SPEED_MEDIUM,
            '压缩速度',
            '请选择压缩速度（越快压缩率越低）',
            self.presetComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.VIDEO,
            '视频比特率',
            '请选择压缩后的视频比特率',
            self.vbComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.MUSIC,
            '音频编码器',
            '请选择压缩使用的音频编码器',
            self.acodecComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.SCROLL,
            '音频比特率',
            '请选择压缩后的音频比特率',
            self.abComboBox
        )
        self.headerCard.addGroup(
            Icon.FPS,
            '帧率',
            '请选择压缩后的帧率',
            self.fpsComboBox
        )
        self.headerCard.addGroup(
            FluentIcon.PLAY_SOLID,
            '开始压缩',
            '点击开始压缩',
            self.startBtn
        )

    def __connectSignals(self):
        self.selectBtn.clicked.connect(self.selectFile)
        self.saveBtn.clicked.connect(self.saveFile)
        self.startBtn.clicked.connect(self.compressVideo)

    def selectFile(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择视频文件", "",
                                                   f"视频文件 ({' *.'.join(self.VIDEO_SUFFIX)})")
        if not file_path:
            return
        self.selectGroup.setContent(f"已选择文件：{file_path}")
        self.filename = file_path

    def saveFile(self):
        file_path, _ = QFileDialog.getSaveFileName(self, "保存视频压缩文件", "output.mp4",
                                                   f"视频文件 ({' *.'.join(self.VIDEO_SUFFIX)})")
        if not file_path:
            return
        self.saveGroup.setContent(f"已保存文件：{file_path}")
        self.output_file = file_path

    def compressVideo(self):
        if not self.filename:
            return
        self.setDialogContent(
            f'正在压缩视频，请稍候...\n压缩视频文件路径：{self.filename}\n压缩输出文件路径：{self.output_file}')
        self.load(
            compress_video,
            self.filename,
            self.output_file,
            scale=self.scaleComboBox.currentText(),
            codec=self.codecComboBox.currentText(),
            crf=self.crfComboBox.currentText(),
            preset=self.presetComboBox.currentText(),
            video_bitrate=self.vbComboBox.currentText(),
            acodec=self.acodecComboBox.currentText(),
            audio_bitrate=self.abComboBox.currentText(),
            r=self.fpsComboBox.currentText(),
            overwrite_output=self.overwriteOutput.isChecked()
        )

    def onFuncSuccess(self, result: Any):
        InfoBar.success('视频压缩成功', f'压缩后的视频文件路径：{self.output_file}', duration=10000,
                        parent=self.window())
